package smack.client.gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.ComponentOrientation;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;

import com.senyint.imsdk.ISdkConfig;
import com.senyint.imsdk.SendPacketException;
import com.senyint.imsdk.SmackHelper;
import com.senyint.imsdk.SmackHelper.ILoginListener;
import com.senyint.imsdk.listener.XMPPConnecionListener;
import com.senyint.imsdk.listener.XMPPMessageListener;
import com.senyint.imsdk.packet.PacketReadExtension;
import com.senyint.imsdk.packet.PacketReadIQ;

public class SmackDemoClientDefault {
	protected static final String TAG = SmackDemoClientDefault.class.getSimpleName();
	
	/************* UI ********************/
	private JFrame frame = null ;
			
    private JTextField hostTextField;

    private JTextField portTextField;

    private JTextField userTextField;

    private JTextField keyTextField;

    private JTextArea messageTextArea;

    private JLabel statusLabel;

    private JButton connect;

    private JButton send;

    private JTalkTabbedPane tabbedPane = null ;
    /************* UI ********************/
    
    /*****************************/
    private final static String CFG = "smack.properties" ;
    private String configPropertiesFile = CFG ;
    private String host = "172.16.201.52" ;
    private Integer port = 5222 ;
    private String user = null ;
    private String password = null ;
	private String serviceName = "testim.cmall.motorsc.com" ; // "uos" ;//
	private String resourceName = "android" ;
    
    private ISdkConfig sdkConfig = null ;
    
    private SmackHelper smackHelper = SmackHelper.me() ;
    
	/*****************************/
    public SmackDemoClientDefault(){}
    public SmackDemoClientDefault(String prop){
    	configPropertiesFile = prop ;
    }
    public static void main(final String[] args) {
        new SmackDemoClientDefault().start();
    }

    private void loadProperties() {
        Properties props = new Properties();
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(configPropertiesFile);
            props.load(fis);
        } catch (Exception e) {
            // ignore
        	e.printStackTrace();
        } finally {
            String ahost = props.getProperty("client.host");
            if (ahost == null || ahost.trim().length()==0) hostTextField.setText(host);
            else {
            	hostTextField.setText(ahost);
            	host = ahost ;
            }

            String aport = props.getProperty("client.port");
            if (aport != null && !aport.isEmpty()) {
            	portTextField.setText(""+port);
            	port = Integer.parseInt(aport);
            }
            else portTextField.setText(port+"");

            String auser = props.getProperty("client.user");
            if (auser != null && !auser.isEmpty()) {
            	userTextField.setText(auser);
            	user = auser ;
            }

            String akey = props.getProperty("client.key");
            if (akey != null && !akey.isEmpty()) {
            	keyTextField.setText(akey);
            	password  = akey ;
            }

            String message = props.getProperty("client.message");
            if (message != null && !message.isEmpty()) {
            	messageTextArea.setText(message);
            }
            else messageTextArea.setText("");

            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    // ignore
                }
            }
        }
    }

    private void saveProperties() {
        FileOutputStream fos = null;
        final Properties props = new Properties();
        try {
            props.setProperty("client.host", hostTextField.getText());
            props.setProperty("client.port", portTextField.getText());
            props.setProperty("client.user", userTextField.getText());
            props.setProperty("client.key", keyTextField.getText());
            props.setProperty("client.message", messageTextArea.getText());

            fos = new FileOutputStream(configPropertiesFile);
            props.store(fos, null);
        } catch (Exception e) {
            // ignore

        } finally {

            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    // ignore
                }
            }
        }
    }

    public void start() {
    	sdkConfig = new ISdkConfig(){
			@Override
    		public String getUserName() {
    			return user = userTextField.getText();
    		}

    		@Override
    		public String getServiceName() {
    			return serviceName  ;//im.cmall.motorsc.com
    		}

    		@Override
    		public String getResourceName() {
    			return resourceName ;
    		}

    		@Override
    		public String getUserJID() {
    			return user+"@"+getServiceName()+"/"+getResourceName();
    		}

    		@Override
    		public String getPassword() {
    			return password = keyTextField.getText();
    		}

    		@Override
    		public void clear() {
    			userTextField.setText("");
    			user = null ;
    			password = null ;
    		}

			@Override
			public String getHost() {
				return host=hostTextField.getText() ;
			}

			@Override
			public Integer getPort() {
				return port = portTextField.getText().isEmpty()?5222:Integer.parseInt(portTextField.getText()) ;
			}
    	};
        
    	XMPPConnecionListener mConnectionListener = new XMPPConnecionListener(){
   			@Override
   			public void onUserConflict() {
   				super.onUserConflict();
   				log("connection conflicted.");
   				onDisconnected();
   				onAuthenticationFailed();
   				smackHelper.onLogout();
   			}
   			@Override
   			public void connectionClosed() {
   				log("connection closed.");
   				onDisconnected();
   				onAuthenticationFailed();
//   				smackHelper.onDisconnect();
   			}
   			@Override
   			public void connectionClosedOnError(Exception ex) {
   				super.connectionClosedOnError(ex);
   				log("connection error.");
   				
   				onDisconnected();
//   				smackHelper.onDisconnect();
   			}
   			
   			@Override
   			public void reconnectionSuccessful() {
   				log(TAG, "reconnectionSuccessful");
   				onAuthenticated();
   			}
   
   			@Override
   			public void reconnectionFailed(Exception e) {
   				log(TAG, "re fail:"+e.getMessage());
//   				onAuthenticationFailed();
   				onDisconnected();
   				smackHelper.onDisconnect();
   			}
   		};
   		XMPPMessageListener messageListener = new XMPPMessageListener(){
   			@Override
   			public void onHandleMessage(Message message) {
   				super.onHandleMessage(message);
   				log("recv2////",message.toXML());
   				onMessageReceved(message);
   			}
   			@Override
   			public void sendPacket(Packet packet) throws SendPacketException {
   				log("send2////",packet.toXML());
   				onSend(packet);
   			}
   			
   			@Override
   			public void onFeedbackServer(final String msgId){
   				if(msgId == null||"null".equalsIgnoreCase(msgId)) return ;
   				log("feeed////",msgId);
   				this.onHandleInBackgroud(new Runnable(){
   					@Override
   					public void run() {
   						try {
   							IQ packet = new PacketReadIQ(new PacketReadExtension(msgId));
   							packet.setFrom(sdkConfig.getUserJID());
   							sendPacket(packet);
   						} catch (SendPacketException e) {
   							// TODO if 发送失败如何，这里意味着服务器会重复该消息，是否所有发送消息都应该缓存,
   							e.printStackTrace();
   						}
   					}
   				});
   			}
   		};
    	
    	log("smack helper  res:"+smackHelper.getSdkConfig().getResourceName()) ;
    	smackHelper.create(sdkConfig);
    	log("smack helper  res 222 :"+smackHelper.getSdkConfig().getResourceName()) ;
    	
    	smackHelper.setConnectionListener(mConnectionListener);
    	smackHelper.setXMPPMessageListener(messageListener);
    	
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (Exception e) {
                    // ignore
                }

                frame = new JFrame("Smack Client v2");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setResizable(true);
                frame.setMinimumSize(new Dimension(800, 600));
                frame.addWindowListener(new WindowListener() {

                    @Override
                    public void windowOpened(WindowEvent arg0) {
                    }

                    @Override
                    public void windowIconified(WindowEvent arg0) {
                    }

                    @Override
                    public void windowDeiconified(WindowEvent arg0) {
                    }

                    @Override
                    public void windowDeactivated(WindowEvent arg0) {
                    }

                    @Override
                    public void windowClosing(WindowEvent arg0) {
                    	Toolkit.getDefaultToolkit().beep();
                    	if(JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(null,"Quit", "quit now?",JOptionPane.YES_NO_OPTION )){
                    		SmackDemoClientDefault.this.saveProperties();
                            onLogout();
                    	}
                        
                    }

					@Override
                    public void windowClosed(WindowEvent arg0) {
                    }

                    @Override
                    public void windowActivated(WindowEvent arg0) {
                    }
                });

                FlowLayout flowLayout = new FlowLayout();
                flowLayout.setAlignment(FlowLayout.LEFT);
                Container contentPane = frame.getContentPane();
                contentPane.setLayout(new BorderLayout());

                // Connection Panel
                JPanel connectionPanel = new JPanel();
                connectionPanel.setLayout(new BoxLayout(connectionPanel, BoxLayout.Y_AXIS));
                connectionPanel.setBorder(BorderFactory.createLoweredBevelBorder());
                contentPane.add(connectionPanel, BorderLayout.NORTH);

                JPanel hostAndPortPanel = new JPanel();
                connectionPanel.add(hostAndPortPanel);
                hostAndPortPanel.setLayout(flowLayout);
                hostAndPortPanel.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
                hostAndPortPanel.setAlignmentX(Component.LEFT_ALIGNMENT);

                JLabel hostLabel = new JLabel("HOST");
                hostTextField = new JTextField();
                hostTextField.setPreferredSize(new Dimension(192, 24));
                hostAndPortPanel.add(hostLabel);
                hostAndPortPanel.add(hostTextField);

                JLabel portLabel = new JLabel("PORT");
                portTextField = new JTextField();
                portTextField.setPreferredSize(new Dimension(64, 24));
                hostAndPortPanel.add(portLabel);
                hostAndPortPanel.add(portTextField);

                JPanel userAndKeyPanel = new JPanel();
                connectionPanel.add(userAndKeyPanel);
                userAndKeyPanel.setLayout(flowLayout);
                userAndKeyPanel.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
                userAndKeyPanel.setAlignmentX(Component.LEFT_ALIGNMENT);

                JLabel userLabel = new JLabel("USER");
                userTextField = new JTextField();
                userTextField.setPreferredSize(new Dimension(192, 24));
                userAndKeyPanel.add(userLabel);
                userAndKeyPanel.add(userTextField);

                JLabel keyLabel = new JLabel("KEY");
                keyTextField = new JPasswordField();
                keyTextField.setPreferredSize(new Dimension(192, 24));
                userAndKeyPanel.add(keyLabel);
                userAndKeyPanel.add(keyTextField);

                // Center Panel
                GridBagConstraints gridBagConstraints = new GridBagConstraints();
                gridBagConstraints.fill = GridBagConstraints.BOTH;
                gridBagConstraints.weightx = 1;
                gridBagConstraints.weighty = 3;
                JPanel centerPanel = new JPanel();
                centerPanel.setLayout(new GridBagLayout());
                contentPane.add(centerPanel, BorderLayout.CENTER);

                tabbedPane = new JTalkTabbedPane();
//                tabbedPane.setCloseButtonEnabled(true);
                gridBagConstraints.gridx = 0;
                gridBagConstraints.gridy = 0;
                centerPanel.add(tabbedPane, gridBagConstraints);
                
                JPanel outgoingPanel = new JPanel();
                outgoingPanel.setLayout(new BorderLayout());
                outgoingPanel.setBorder(BorderFactory.createLoweredBevelBorder());
                gridBagConstraints.gridx = 0;
                gridBagConstraints.gridy = 1;
                centerPanel.add(outgoingPanel, gridBagConstraints);

                JLabel outgoingLabel = new JLabel("Message");
                outgoingLabel.setLayout(flowLayout);
                outgoingLabel.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
                outgoingLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
                outgoingPanel.add(outgoingLabel, BorderLayout.NORTH);

                messageTextArea = new JTextArea();
//                messageTextArea.setEditable(false);
//                messageTextArea.setBackground(new Color(211, 211, 211));
                messageTextArea.setLineWrap(true);
                messageTextArea.setMaximumSize(new Dimension(0, 100));
                messageTextArea.setMinimumSize(new Dimension(0, 100));
                JScrollPane outgoingTextAreaScroll = new JScrollPane(messageTextArea, 
                                                                     JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, 
                                                                     JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
                outgoingPanel.add(outgoingTextAreaScroll, BorderLayout.CENTER);

                // Status Panel
                JPanel statusPanel = new JPanel();
                statusPanel.setLayout(flowLayout);
                statusPanel.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
                statusPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
                contentPane.add(statusPanel, BorderLayout.SOUTH);

                statusLabel = new JLabel("Not connected");
                statusPanel.setBorder(BorderFactory.createLoweredBevelBorder());
                statusPanel.add(statusLabel);

                // Buttons
                connect = new JButton("CONNECT");
                connect.setMnemonic(KeyEvent.VK_C);
                userAndKeyPanel.add(connect);
                send = new JButton("SEND");
                send.setEnabled(false);
                send.setMnemonic(KeyEvent.VK_S);
                userAndKeyPanel.add(send);

                final JButton addFriend = new JButton("new Friend");
                userAndKeyPanel.add(addFriend);
                
                final ActionListener actionListener = new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent ae) {
                        if (ae.getSource() == connect) {
                        	if(smackHelper.isAuthenticated()){
                        		onLogout();
                        	}else{
                        		onConnect();
                        	}
                        	
                        } else if (ae.getSource() == send) {
                            onSend();
                        } else if(ae.getSource() == addFriend){
                        	showAddFriendDialog();
                        }
                    }
                };

                connect.addActionListener(actionListener);
                send.addActionListener(actionListener);
                addFriend.addActionListener(actionListener);
                
                // load properties
                SmackDemoClientDefault.this.loadProperties();
                
                Runtime.getRuntime().addShutdownHook(new Thread(){
					@Override
					public void run() {
						log("the application exit.");
						onLogout();
					}
                });
                frame.pack();
                frame.setVisible(true);
            }
        });
    }
    
    class MyDialog extends JDialog implements ActionListener{
       JLabel label1 = new JLabel("input name");
       JTextField inputName = new JTextField(50);

       JButton ok = new JButton("确定");
       JButton cancel = new JButton("取消");
       
       MyDialog(JFrame parent, boolean modal) {
           super(parent,modal);
           setTitle("New Friend");
           setSize(260,140);
           setResizable(false);
           setLayout(null);
           add(label1);
           add(inputName);
           label1.setBounds(50, 30, 65, 20);
           inputName.setBounds(50, 60, 65, 20);

           add(ok);
           add(cancel);

           ok.setBounds(60, 100, 60, 25);
           cancel.setBounds(140, 100, 60, 25);
           ok.addActionListener(this);
           cancel.addActionListener(this);
       }

       public void actionPerformed(ActionEvent e){
           if (e.getSource()==ok)
           {
        	   String text =inputName.getText();
        	   if(text.trim().length()>0){
        		   onAddFriend(text,text);
        		   dispose();
        	   }
           }else{
        	   dispose();
           }

           
       }
       
       public String getInput(){
    	   return inputName.getText();
       }
       
    }
    
    private void log(String tag, String string) {
		System.out.println(tag+"---"+string);
	}

    public void showAddFriendDialog(){
    	MyDialog dlg = new MyDialog(frame,true);
//        dlg.show();
    	dlg.setVisible(true);
    }
    
    public JTalkTabbedPane.LogPane onAddFriend(String uid,String name){
    	return tabbedPane.addChat(uid,name);
    }
    
    public void onConnect(){
        if (!smackHelper.isAuthenticated()) {
            hostTextField.setEnabled(false);
            portTextField.setEnabled(false);
            userTextField.setEnabled(false);
            keyTextField.setEnabled(false);
            statusLabel.setText("Connecting");
            
            String user = userTextField.getText();
            String password = keyTextField.getText();
            onLogin(user,password);

        }  
    }
    
    /**
     * send to the user
     */
    public void onSend(){
    	String msg = messageTextArea.getText();
    	if(msg==null||msg.trim().length()==0){
    		return ;
    	}
    	String to = tabbedPane.getCurrentContent() ;
    	smackHelper.onSend(to, msg);
		onMessageSent(to,msg);
		
		messageTextArea.setText("");
    }

    /**
     * send the packet
     * @param packet
     */
    public void onSend(Packet packet){
    	log("send:"+packet.toXML());
    	if(smackHelper.isAuthenticated()){
    		smackHelper.onSend(packet);
    	}
    }
    
    public void onLogin(final String uid,final String token){
    	final ILoginListener listener = new ILoginListener(){
			@Override
			public void onSuccess() {
				user = uid ;
                password = token ;
                log("on login ok,user:"+user+","+password);
                connect.setText("DISCONNECT");
                connect.setEnabled(true);
                onAuthenticated();
			}

			@Override
			public void onFailed() {
				connect.setText("CONNECT");
				connect.setEnabled(true);
			}};
		log("smack demo onlogin.............");
    	SwingUtilities.invokeLater(new Runnable() {
            public void run() {
            	log("host------->:"+host +"/"+sdkConfig.getHost());
            	smackHelper.onLogin(uid, token, listener);
            }
    	});
    }
    
    private void log(String msg) {
    	System.out.println(msg);
	}

	public void onLogout() {
    	 try {
             smackHelper.onDisconnect();
         } catch (Exception e) {
             e.printStackTrace();

         } finally {
             hostTextField.setEnabled(true);
             portTextField.setEnabled(true);
             userTextField.setEnabled(true);
             keyTextField.setEnabled(true);
             connect.setEnabled(true);
             connect.setText("CONNECT");
//             messageTextArea.setEditable(false);
             messageTextArea.setBackground(new Color(211, 211, 211));
             statusLabel.setText("Disconnected");
         }
	}
    
    public void onDisconnected(){
        hostTextField.setEnabled(true);
        portTextField.setEnabled(true);
        userTextField.setEnabled(true);
        keyTextField.setEnabled(true);
        connect.setEnabled(true);
        connect.setText("CONNECT");
//        messageTextArea.setEditable(false);
        messageTextArea.setBackground(new Color(211, 211, 211));
        statusLabel.setText("Disconnected");
        send.setEnabled(false);
    }

    public void onAuthenticated(){
    	statusLabel.setText("Connected");
        messageTextArea.setEditable(true);
        messageTextArea.setBackground(Color.WHITE);
        send.setEnabled(true);
    }
    
    public void onAuthenticationFailed(){
    	statusLabel.setText("not authenticated");
    	statusLabel.setText("Authentication failed");
    }

    public void onMessageReceved(Message message){
    	if(message.getBody() == null)
    		return ;
    	String from = message.getFromNode();
    	log("onMessageReceved:"+message.toXML());
    	JTalkTabbedPane.LogPane p = tabbedPane.find(from) ;
    	
    	if(p == null){
    		p = onAddFriend(from, from);
    	}
    	
    	if( p != null){
    		p.appendMessage(from,message.getBody());
    	}
    }
    
    public void onMessageSent(String to,String msg){
    	if(msg == null)
    		return ;

    	JTalkTabbedPane.LogPane p = tabbedPane.find(to) ;
    	
    	if(p == null){
    		p = onAddFriend(to, to);
    	}
    	
    	if( p != null){
    		p.appendMessage(sdkConfig.getUserName(),msg);
    	}
    }
    
    ////////////////////////////////////////////////////
}
